#include "sys_hardware.h"

static void uart0_init(void);
static void adc_init();
static void uart1_init(void);
static void gpio_base_init();
static void pmu_init(void);
static void atime_pwm_init(void);
static void gptim0_init_10ms();

void sys_nvic_init(void)
{
    FL_NVIC_ConfigTypeDef InterruptConfigStruct;
    InterruptConfigStruct.preemptPriority = 2;
    FL_NVIC_Init(&InterruptConfigStruct, UART1_IRQn);

    InterruptConfigStruct.preemptPriority = 2;
    FL_NVIC_Init(&InterruptConfigStruct, UART0_IRQn);

    InterruptConfigStruct.preemptPriority = 1;
    FL_NVIC_Init(&InterruptConfigStruct, GPTIM0_IRQn);
}

void sys_hardware_init(void)
{
    uart0_init();
    uart1_init();
    adc_init();
    gpio_base_init();
    gptim0_init_10ms();
    // pmu_init();
    FL_DMA_Enable(DMA);
    atime_pwm_init();
}

static void uart0_init(void)
{
    FL_GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.pin = FL_GPIO_PIN_14 | FL_GPIO_PIN_13;
    GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_DISABLE;
    GPIO_InitStruct.remapPin = FL_DISABLE;
    FL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    FL_UART_InitTypeDef defaultInitStruct;
    defaultInitStruct.clockSrc = FL_RCC_UART0_CLK_SOURCE_RCHF;
    defaultInitStruct.baudRate = 9600;
    defaultInitStruct.dataWidth = FL_UART_DATA_WIDTH_8B;
    defaultInitStruct.stopBits = FL_UART_STOP_BIT_WIDTH_1B;
    defaultInitStruct.parity = FL_UART_PARITY_NONE;
    defaultInitStruct.transferDirection = FL_UART_DIRECTION_NONE;
    FL_UART_Init(UART0, &defaultInitStruct);

    FL_DMA_InitTypeDef dma_init;
    dma_init.periphAddress = FL_DMA_PERIPHERAL_FUNCTION2;
    dma_init.direction = FL_DMA_DIR_RAM_TO_PERIPHERAL;
    dma_init.memoryAddressIncMode = FL_DMA_MEMORY_INC_MODE_INCREASE;
    dma_init.flashAddressIncMode = FL_DMA_CH7_FLASH_INC_MODE_INCREASE;
    dma_init.dataSize = FL_DMA_BANDWIDTH_8B;
    dma_init.priority = FL_DMA_PRIORITY_HIGH;
    dma_init.circMode = FL_DISABLE;
    FL_DMA_Init(DMA, &dma_init, FL_DMA_CHANNEL_2);
}

// 与ESP32通讯
static void uart1_init(void)
{
    FL_GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.pin = FL_GPIO_PIN_3 | FL_GPIO_PIN_2;
    GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_DISABLE;
    GPIO_InitStruct.remapPin = FL_DISABLE;
    FL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    FL_UART_InitTypeDef defaultInitStruct;
    defaultInitStruct.clockSrc = FL_RCC_UART1_CLK_SOURCE_RCHF;
    defaultInitStruct.baudRate = 115200;
    defaultInitStruct.dataWidth = FL_UART_DATA_WIDTH_8B;
    defaultInitStruct.stopBits = FL_UART_STOP_BIT_WIDTH_1B;
    defaultInitStruct.parity = FL_UART_PARITY_NONE;
    defaultInitStruct.transferDirection = FL_UART_DIRECTION_NONE;
    FL_UART_Init(UART1, &defaultInitStruct);

    FL_DMA_InitTypeDef dma_init;
    dma_init.periphAddress = FL_DMA_PERIPHERAL_FUNCTION3;
    dma_init.direction = FL_DMA_DIR_RAM_TO_PERIPHERAL;
    dma_init.memoryAddressIncMode = FL_DMA_MEMORY_INC_MODE_INCREASE;
    dma_init.flashAddressIncMode = FL_DMA_CH7_FLASH_INC_MODE_INCREASE;
    dma_init.dataSize = FL_DMA_BANDWIDTH_8B;
    dma_init.priority = FL_DMA_PRIORITY_HIGH;
    dma_init.circMode = FL_DISABLE;
    FL_DMA_Init(DMA, &dma_init, FL_DMA_CHANNEL_6);
}

static void adc_init()
{
    FL_GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.pin = FL_GPIO_PIN_0 | FL_GPIO_PIN_1 | FL_GPIO_PIN_11;
    GPIO_InitStruct.mode = FL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_DISABLE;
    GPIO_InitStruct.remapPin = FL_DISABLE;
    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    GPIO_InitStruct.pin = FL_GPIO_PIN_7;
    FL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    // 1M 采样率
    FL_ADC_CommonInitTypeDef CommonInitStruct;
    CommonInitStruct.clockSource = FL_RCC_ADC_CLK_SOURCE_RCHF;
    CommonInitStruct.clockPrescaler = FL_RCC_ADC_PSC_DIV8;
    FL_ADC_CommonInit(&CommonInitStruct);

    FL_ADC_InitTypeDef defaultInitStruct;
    defaultInitStruct.conversionMode = FL_ADC_CONV_MODE_SINGLE;
    defaultInitStruct.autoMode = FL_ADC_SINGLE_CONV_MODE_AUTO;
    defaultInitStruct.waitMode = FL_ENABLE;
    defaultInitStruct.overrunMode = FL_ENABLE;
    defaultInitStruct.scanDirection = FL_ADC_SEQ_SCAN_DIR_FORWARD;
    defaultInitStruct.externalTrigConv = FL_ADC_TRIGGER_EDGE_NONE;
    defaultInitStruct.triggerSource = FL_ADC_TRGI_PA8;
    defaultInitStruct.fastChannelTime = FL_ADC_FAST_CH_SAMPLING_TIME_4_ADCCLK;
    defaultInitStruct.lowChannelTime = FL_ADC_SLOW_CH_SAMPLING_TIME_160_ADCCLK;
    defaultInitStruct.oversamplingMode = FL_ENABLE;
    defaultInitStruct.overSampingMultiplier = FL_ADC_OVERSAMPLING_MUL_32X;
    defaultInitStruct.oversamplingShift = FL_ADC_OVERSAMPLING_SHIFT_5B;
    FL_ADC_Init(ADC, &defaultInitStruct);

    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_INTERNAL_AVREF);
    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_EXTERNAL_CH2);
    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_EXTERNAL_CH3);
    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_EXTERNAL_CH4);
    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_EXTERNAL_CH8);

    FL_ADC_EnableDMAReq(ADC);

    FL_DMA_InitTypeDef DMA_InitStruct = {0};
    DMA_InitStruct.periphAddress = FL_DMA_PERIPHERAL_FUNCTION1;            // 配置DMA通道功能
    DMA_InitStruct.direction = FL_DMA_DIR_PERIPHERAL_TO_RAM;               // 配置DMA通道方向
    DMA_InitStruct.memoryAddressIncMode = FL_DMA_MEMORY_INC_MODE_INCREASE; // 配置RAM的增减方向
    DMA_InitStruct.dataSize = FL_DMA_BANDWIDTH_16B;                        // 配置DMA传输位宽
    DMA_InitStruct.priority = FL_DMA_PRIORITY_HIGH;                        // 配置DMA通道优先级
    DMA_InitStruct.circMode = FL_DISABLE;                                  // 配置DMA通道循环缓存
    FL_DMA_Init(DMA, &DMA_InitStruct, FL_DMA_CHANNEL_4);
}

static void gpio_base_init()
{
    FL_GPIO_InitTypeDef gpio;
    gpio.pin = FL_GPIO_PIN_6 | FL_GPIO_PIN_7;
    gpio.mode = FL_GPIO_MODE_OUTPUT;
    gpio.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    gpio.pull = FL_DISABLE;
    gpio.remapPin = FL_DISABLE;
    FL_GPIO_Init(GPIOA, &gpio);

    gpio.pin = FL_GPIO_PIN_14;
    FL_GPIO_Init(GPIOB, &gpio);

    gpio.pin = FL_GPIO_PIN_6;
    FL_GPIO_Init(GPIOD, &gpio);

    gpio.pin = FL_GPIO_PIN_5 | FL_GPIO_PIN_8 | FL_GPIO_PIN_9;
    gpio.mode = FL_GPIO_MODE_INPUT;
    FL_GPIO_Init(GPIOA, &gpio);

    gpio.pin = FL_GPIO_PIN_2 | FL_GPIO_PIN_3 | FL_GPIO_PIN_13;
    FL_GPIO_Init(GPIOB, &gpio);

    gpio.pin = FL_GPIO_PIN_4 | FL_GPIO_PIN_5 | FL_GPIO_PIN_6 | FL_GPIO_PIN_8 | FL_GPIO_PIN_9;
    FL_GPIO_Init(GPIOC, &gpio);

    gpio.pin = FL_GPIO_PIN_9 | FL_GPIO_PIN_1;
    gpio.mode = FL_GPIO_MODE_INPUT;
    FL_GPIO_Init(GPIOC, &gpio);
}

static void pmu_init(void)
{
    FL_PMU_SleepInitTypeDef PMU_InitStruct;
    PMU_InitStruct.deepSleep = FL_PMU_SLEEP_MODE_NORMAL;
    PMU_InitStruct.LDOLowPowerMode = FL_PMU_LDO_LPM_DISABLE;
    PMU_InitStruct.wakeupFrequency = FL_PMU_RCHF_WAKEUP_FREQ_8MHZ;
    PMU_InitStruct.wakeupDelay = FL_PMU_WAKEUP_DELAY_2US;
    PMU_InitStruct.coreVoltageScaling = FL_DISABLE;
    FL_PMU_Sleep_Init(PMU, &PMU_InitStruct);
}

void atime_pwm_init(void)
{
    FL_ATIM_InitTypeDef TimerBase_InitStruct;

    TimerBase_InitStruct.clockSource = FL_RCC_ATIM_CLK_SOURCE_APB2CLK;
    TimerBase_InitStruct.prescaler = 4;
    TimerBase_InitStruct.counterMode = FL_ATIM_COUNTER_DIR_UP;
    TimerBase_InitStruct.autoReload = 255;
    TimerBase_InitStruct.autoReloadState = FL_ENABLE;
    TimerBase_InitStruct.clockDivision = FL_ATIM_CLK_DIVISION_DIV1;
    TimerBase_InitStruct.repetitionCounter = 0;

    FL_ATIM_Init(ATIM, &TimerBase_InitStruct);

    FL_GPIO_InitTypeDef GPIO_InitStruct;

    FL_ATIM_OC_InitTypeDef ATIM_InitStruct;

    /* PB4 ATIM_CH1 */
    GPIO_InitStruct.pin = FL_GPIO_PIN_4 | FL_GPIO_PIN_5;
    GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_DISABLE;
    GPIO_InitStruct.remapPin = FL_DISABLE;
    FL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.pin = FL_GPIO_PIN_10;
    GPIO_InitStruct.remapPin = FL_ENABLE;
    FL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    ATIM_InitStruct.OCMode = FL_ATIM_OC_MODE_PWM1;
    ATIM_InitStruct.OCState = FL_ENABLE;
    ATIM_InitStruct.OCNState = FL_DISABLE;
    ATIM_InitStruct.OCPolarity = FL_ATIM_OC_POLARITY_NORMAL;
    ATIM_InitStruct.OCNPolarity = FL_ATIM_OCN_POLARITY_NORMAL;
    ATIM_InitStruct.OCFastMode = FL_DISABLE;
    ATIM_InitStruct.OCPreload = FL_ENABLE;
    ATIM_InitStruct.compareValue = 0;
    ATIM_InitStruct.OCIdleState = FL_ATIM_OC_IDLE_STATE_LOW;
    ATIM_InitStruct.OCETRFStatus = FL_DISABLE;
    ATIM_InitStruct.OCNIdleState = FL_ATIM_OCN_IDLE_STATE_LOW;

    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_1, &ATIM_InitStruct);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_2, &ATIM_InitStruct);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_3, &ATIM_InitStruct);
}

void gptim0_init_10ms()
{
    FL_GPTIM_InitTypeDef TimerBaseInitStruct;

    TimerBaseInitStruct.prescaler = 32000 - 1;
    TimerBaseInitStruct.counterMode = FL_GPTIM_COUNTER_DIR_UP;
    TimerBaseInitStruct.autoReload = 10;
    TimerBaseInitStruct.autoReloadState = FL_ENABLE;
    TimerBaseInitStruct.clockDivision = FL_GPTIM_CLK_DIVISION_DIV1;
    FL_GPTIM_Init(GPTIM0, &TimerBaseInitStruct);

    FL_GPTIM_ClearFlag_Update(GPTIM0);
}

void HardFault_Handler(void)
{
    NVIC_SystemReset();
    for (;;)
    {
    }
}

#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN Assert_Failed */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END Assert_Failed */
}
#endif /* USE_FULL_ASSERT */
